from mtp.model import *
from mtp.model import ObjBase
from mtp.lib.plugin import Plugin
from mtp.lib.base import *
from datetime import datetime
from mtp.lib import pageetags 

from lxml import html

import logging
log = logging.getLogger(__name__)


CommentsTable = Table('comments', plugin_meta, 
    Column('id', Integer, primary_key=True, autoincrement=True),
    Column('page_id', Integer, ForeignKey(PagesTable.c.id)),
    Column('parent_id', Integer, ForeignKey("comments.id")),
    Column('created', DateTime, default=datetime.now),
    Column('updated', DateTime, onupdate=datetime.now),
    Column('user_id', Integer, ForeignKey(UsersTable.c.id)),
    Column('body', Text),
)

class Comment(ObjBase):
    @classmethod
    def getForPage(klass, page_id):
        return (Session.query(klass)
                .filter(klass.page_id==page_id)
                .filter(klass.parent_id==None)
                .order_by(klass.created)
        )

    @classmethod
    def createForPage(klass, page, user, text, parent=None):
        comment = klass(page_id=page.id,
            user_id=(user.id if user else None), 
            body=text,
            parent_id=(parent.id if parent else None),
        )
        comment.save()
        return comment

    def delete(self):
        for child in self.children: 
            child.delete()
        ObjBase.delete(self)

mapper(Comment, CommentsTable, properties={
    'user': relation(User),
    'children': relation(Comment, 
        backref=backref('parent', remote_side=[CommentsTable.c.id]))
})

class CommentsController(BaseController):
    @needs_perm('comment', 'view')
    def index(self, page_id):
        c.page = Page.getByTitle(page_id)
        if c.page is None: abort(404)
        c.comments = Comment.getForPage(c.page.id)
        if request.params.get('fragment'):
            return render('/comments/list_frag.html')
        return render('/comments/list.html')

    @needs_perm('comment', 'create')
    def new(self, page_id):
        c.page = Page.getByTitle(page_id)
        reply_to_id = request.params.get('reply_to')
        if reply_to_id:
            c.in_reply_to = Comment.get(reply_to_id)
        if c.page is None: abort(404)
        c.comments = Comment.getForPage(c.page.id)
        if request.params.get('fragment'):
            return render('/comments/new_frag.html')
        return render('/comments/new.html')    

    @needs_perm('comment', 'create')
    def create(self, page_id):
        page = Page.getByTitle(page_id)
        if not page: abort(404)
        in_reply_to_id = request.params.get('reply_to')
        if in_reply_to_id:
            in_reply_to = Comment.get(in_reply_to_id)
            if not in_reply_to: abort(417)
        else: 
            in_reply_to = None
        Comment.createForPage(page, session.get('user'), request.POST['body'], 
            parent=in_reply_to)
        pageetags.bump_page_etag(page_id)
        if is_ajax():
            c.page = page
            c.comments = Comment.getForPage(c.page.id)
            return render('/comments/list_frag.html')
        redirect_to( h.url_for('page', id=page_id) )

    @needs_perm('comment', 'delete')
    def delete(self, page_id, id):
        page = Page.getByTitle(page_id)
        if not page: abort(404)
        comment = Comment.get(id)
        if not comment: abort(404)
        comment.delete()
        redirect_to(h.url_for('page', id=page_id))

    def update(self, page_id, id):
        log.debug('update %s' % str((page_id, id)))
        page = Page.getByTitle(page_id)
        if not page: abort(404)
        comment = Comment.get(id)
        if not comment: abort(404)
        if not (has_perm('comment', 'edit') or
                c.user == comment.user):
            abort(403)
        comment.body = request.POST['body']
        comment.save()
        if is_ajax():
            c.page = page
            c.comments = Comment.getForPage(c.page.id)
            return render('/comments/list_frag.html')
        redirect_to(h.url_for('page', id=page_id))

    def edit(self, page_id, id):
        c.page = Page.getByTitle(page_id)
        if not c.page: abort(404)
        c.comment = Comment.get(id)
        if not c.comment: abort(404)
        if not (has_perm('comment', 'edit') or 
                c.user == c.comment.user):
            abort(403)
        if request.params.get('fragment'):
            return render('/comments/new_frag.html')
        return render('/comments/edit.html')
    

class CommentsPlugin(Plugin):
    tables = [CommentsTable]

    def __init__(self, **options):
        #config['mtp.plugin_wikimodifiers'].append(self.modifyWiki)
        config['mtp.controllers']['comments'] = CommentsController
        config['mtp.map'].pageResource('comment', 'comments')
        
        config['mtp.extra_css'].append('/comments/comments.css')
        config['mtp.permissions']['comment'].update(('create', 'view', 'delete'))
        config['mtp.content.append'][('pages', 'show')].append(self.pageContent)

    def setup(self):
        Plugin.setup(self)
        
        UserPermission.grant(None, 'comment', 'view')

    def pageContent(self):
        if has_perm('comment', 'view'):
            c.comments = Comment.getForPage(c.page.id)
            if c.comments.count() or has_perm('comments', 'create'):
                return mako_render('/comments/page.html')







